package org.dru.clay.util.xml;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Xml {
	public static Node getSingleChild(Element base, String childName) {
		final NodeList list = base.getElementsByTagName(childName);
		if (list == null || list.getLength() < 0) {
			throw new IllegalArgumentException("No child node named '" + childName + "' found");
		}
		if (list.getLength() > 1) {
			throw new IllegalArgumentException("Multiple '" + childName + "' nodes found");
		}
		return list.item(0);
	}

	public static Node getSingleChild(Node base, String childName) {
		final NodeList list = base.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			final Node node = list.item(i);
			if (childName.equals(node.getNodeName())) {
				return node;
			}
		}
		throw new IllegalArgumentException("No child node named '" + childName + "' found");
	}

	public static List<Node> getChildren(final Node parent, final String childNodeName) {
		final List<Node> result = new ArrayList<Node>();
		
		if (parent == null) {
			return result;
		}

		final NodeList nodes = parent.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			final Node node = nodes.item(i);
			if (childNodeName.equals(node.getNodeName())) {
				result.add(node);
			}
		}

		return result;
	}

	public static String getAttribute(Node node, String attributeName) {
		final NamedNodeMap attributes = node.getAttributes();
		final Node attribute = attributes.getNamedItem(attributeName);
		if (attribute == null) {
			return null;
		}
		return attribute.getTextContent();
	}

	public static String getAttribute(Node node, String attributeName, String defaultValue) {
		final NamedNodeMap attributes = node.getAttributes();
		final Node attribute = attributes.getNamedItem(attributeName);
		if (attribute == null) {
			return defaultValue;
		}
		return attribute.getTextContent();
	}

	public static Integer getIntegerAttribute(Node node, String attributeName, Integer defaultValue) {
		final String value = getAttribute(node, attributeName);
		if (value == null) {
			return defaultValue;
		}
		return Integer.parseInt(value);
	}

	public static Boolean getBooleanAttribute(Node node, String attributeName, Boolean defaultValue) {
		final String value = getAttribute(node, attributeName);
		if (value == null) {
			return defaultValue;
		}
		return Boolean.parseBoolean(value);
	}

	@SuppressWarnings("unchecked")
	public static <T extends Enum<T>> T getEnumAttribute(Node node, String attributeName, Class<T> E, T defaultValue) {
		final String value = getAttribute(node, attributeName);
		if (value == null) {
			return defaultValue;
		}
		try {
			for (T val : (T[]) E.getMethod("values").invoke(null)) {
				if (val.name().toLowerCase().equals(value.toLowerCase())) {
					return val;
				}
			}
			return defaultValue;
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}
	}
}
